package com.lp.filter;

import com.lp.constants.RedisConstants;
import com.lp.constants.URIPathPass;
import com.lp.exception.TokenException;
import com.lp.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Configuration
public class HandlerGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private StringRedisTemplate redisTemplate;

    //未登录时，直接可以放行通过的路由
    private String[] passList = {URIPathPass.LOGIN, URIPathPass.REG, URIPathPass.ARTICLE_LIST};

    /**
     * 过滤器
     * @param exchange 交换器，用来获取 request 和 response
     * @param chain 决定是否继续向后执行
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //1.对所有用户放行一下路由
        String path = request.getURI().getPath();
        for(String pass : passList) {
            if(path.equals(pass)) {
                return chain.filter(exchange);
            }
        }
        //2.请求中获取 token
        List<String> tokenList = request.getHeaders().get("token");
        if(tokenList == null) {
            throw new TokenException("token 数据异常");
        }
        String token = tokenList.get(0);
        if(!StringUtils.hasLength(token)) {
            throw new TokenException("token 数据异常");
        }
        //3.检验 token 数据是否合法
        //1) redis 上的 token 是否过期
        if(!redisTemplate.hasKey(RedisConstants.TOKEN + token)) {
            throw new TokenException("非法 token 令牌");
        }
        //2) jwt 校验
        if(!JwtUtils.checkToken(token)) {
            throw new TokenException("非法 token 令牌");
        }
        //4.校验通过
        return chain.filter(exchange);
    }

    /**
     * 当前过滤器的顺序，-1 优先级最高
     * @return
     */
    @Override
    public int getOrder() {
        return -1;
    }

}
